﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Proggy.Data.Entities;
using Newtonsoft.Json;
using Proggy.Web.Cms.Repositories.Membership;
using Proggy.Data;
using Proggy.Data.Abstract;
using Proggy.Web.Cms.Repositories.ContentModel;
using Proggy.Web.Cms.Repositories.Published;

namespace Proggy.Web.Cms.ContentModel
{
    /// <summary>
    /// Converts content models
    /// </summary>
    public class ContentModelConverter : IContentModelConverter
    {
        public ContentModelConverter(IMembershipRepository membRepo, INodeRepository nodeRepo, IContentModelTypeRepository cmtRepo) {
            this._memberRepo = membRepo;
            this._nodeRepo = nodeRepo;
            this._cmtRepo = cmtRepo;
            //this._publishedRepo = publishedRepo;
        }

        public IContentModel ToPublishedAbstractSingle(PublishableNode publishable)
        {
            // check
            if (publishable == null)
            {
                return null;
            }

            // get node type
            var nodeType = getNodeTypeFromNode(publishable.TypeAlias, publishable.ContentModelNameSpace, publishable.TypeAssemblyName);

            //
            try
            {
                //
                IContentModel cm;

                // check content data
                if (string.IsNullOrEmpty(publishable.SavedContentModelData))
                {
                    cm = (IContentModel)Activator.CreateInstance(nodeType, this._cmtRepo, this._memberRepo);
                }
                else
                {
                    cm = (IContentModel)JsonConvert.DeserializeObject(publishable.SavedContentModelData, nodeType, new JsonSerializerSettings { MissingMemberHandling = MissingMemberHandling.Ignore });
                }

                // set node properties
                cm.FirstCreated = publishable.FirstCreated;
                cm.Id = publishable.PublishableNodeId;
                cm.LastUpdated = publishable.LastPublished != null ? (DateTime)publishable.LastPublished : publishable.LastUpdated;
                cm.Name = publishable.Name;
                cm.OrderInParent = publishable.OrderInParent;
                if (publishable.ParentNode != null) cm.ParentId = publishable.ParentNode.PublishableNodeId;
                cm.Template = publishable.Template;
                cm.UrlSlug = publishable.UrlPortion;
                cm.TypeAlias = publishable.TypeAlias;
                cm.IsRoot = publishable.IsRoot;
                cm.UniqueAlias = publishable.UniqueAlias;
                cm.FirstCreatedMemberUsername = publishable.FirstCreatedUsername;
                cm.LastUpdatedMemberUsername = publishable.LastUpdatedUsername;
                cm.LeveInTree = publishable.LevelInTree;
                //cm.FirstCreatedMember = new Membership.ProggyMember { };// this.MembershipRepository.GetMember(node.FirstCreatedUsername, false);
                //cm.LastUpdatedMember = new Membership.ProggyMember { };// this.MembershipRepository.GetMember(node.LastPublishedUsername, false);                

                //
                return cm;
            }
            catch
            {
                throw;
            }
        }

        public IContentModel ToDraftAbstractSingle(PublishableNode publishable)
        {
            // check
            if (publishable == null)
            {
                return null;
            }

            // get draft
            DraftNode draft = null;
            if (publishable.DraftNode == null)
            {
                draft = this._nodeRepo.CreateAndGetDraftForPublished(publishable);                
            }
            else
            {
                draft = publishable.DraftNode;
            }

            // check
            if (draft == null)
            {
                throw new NullReferenceException("PublishableNode.RelatedDraftNode");
            }

            // start output
            IContentModel cm;// = null;

            // get type
            var type = this.getNodeTypeFromNode(draft.TypeAlias, draft.ContentModelNameSpace, draft.TypeAssemblyName);

            //
            try
            {
                // check content data
                if (string.IsNullOrEmpty(draft.SavedContentModelData))
                {
                    cm = (IContentModel)Activator.CreateInstance(type, this._cmtRepo, this._memberRepo);
                }
                else
                {
                    cm = (IContentModel)JsonConvert.DeserializeObject(draft.SavedContentModelData, type, new JsonSerializerSettings { MissingMemberHandling = MissingMemberHandling.Ignore, ConstructorHandling= ConstructorHandling.Default });
                }

                // set node properties
                cm.FirstCreated = publishable.FirstCreated;
                cm.Id = publishable.PublishableNodeId;
                cm.LastUpdated = draft.LastUpdated;
                cm.Name = draft.Name;
                cm.OrderInParent = publishable.OrderInParent;
                if (!publishable.IsRoot) cm.ParentId = publishable.ParentNode.PublishableNodeId;
                cm.Template = draft.Template;
                cm.UrlSlug = draft.UrlPortion;
                cm.TypeAlias = draft.TypeAlias;
                cm.IsRoot = publishable.IsRoot;
                cm.UniqueAlias = draft.UniqueAlias;
                cm.FirstCreatedMemberUsername = draft.FirstCreatedUsername;
                cm.LastUpdatedMemberUsername = draft.LastUpdatedUsername;
                cm.LeveInTree = publishable.LevelInTree;
                //cm.FirstCreatedMember = new Membership.ProggyMember { };// this.MembershipRepository.GetMember(draft.FirstCreatedUsername, false);
                //cm.LastUpdatedMember = new Membership.ProggyMember { };// this.MembershipRepository.GetMember(draft.LastUpdatedUsername, false);                
            }
            catch
            {
                throw;
            }

            //
            return cm;
        }

        private Type getNodeTypeFromNode(string alias, string ns, string assmbl)
        {
            var nodeType =
                Type.GetType(ns + "." + alias + ProggyDataConstants.CONTENT_MODEL_APPENDAGE + "," + assmbl);
            return nodeType;
        }

        private IMembershipRepository _memberRepo;

        private INodeRepository _nodeRepo;

        private IContentModelTypeRepository _cmtRepo; 
        
        //private IPublishedContentRepository _publishedRepo;
    }
}
